package com.tianlang.security;

import java.util.List;

import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;

/**
 * 
 * @author mcp
 *
 */
public class ShiroDbRealm extends AuthorizingRealm {
	private static final Logger log = Logger.getLogger(ShiroDbRealm.class);

	/**
	 * 获取用户验证信息，登录时调用,在这个方法中，进行身份验证
	 * 
	 * @param token
	 *            所需验证的token
	 * @return null or 身份信息
	 * @throws AuthenticationException
	 *             验证异常
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		log.info("----------doGetAuthenticationInfo方法被调用----------");
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
		Kv conf = new Kv();
		conf.set("userName", usernamePasswordToken.getUsername());
		SqlPara sqlPara = Db.getSqlPara("user.getByUsername", conf);
		Record account = Db.findFirst(sqlPara);
		if (account != null) {
			if (!account.getStr("password").equals(String.valueOf(usernamePasswordToken.getPassword()))) {
				throw new AuthenticationException("密码错误");
			}
			return new SimpleAuthenticationInfo(account, account.getStr("password"), getName());
		} else {
			throw new AuthenticationException("用户不存在");
		}
	}

	/**
	 * 获取用户授权信息,获取身份信息，我们可以在这个方法中，从数据库获取该用户的权限和角色信息
	 * 
	 * @param principals
	 *            用户身份
	 * @return null or 授权信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		log.info("----------doGetAuthorizationInfo方法被调用----------");
		Record userInPrincipal = (Record) principals.getPrimaryPrincipal();
		// 根据用户获取权限
		SqlPara sqlPara = Db.getSqlPara("user.getPermissions", userInPrincipal.getStr("id"));
		// stringPermissions结构：可访问的路径地址
		List<String> stringPermissions = Db.query(sqlPara.getSql(), sqlPara.getPara()[0]);
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addStringPermissions(stringPermissions);
		return info;
	}

}
